/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.jm.commons.xpath;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 *
 * @author Michael L.R. Marques
 */
public class XPathNodeListIterator implements Iterable<Node> {
    
    //
    private NodeList xmlNodeList;

    /**
     * 
     * @param xmlDocument
     * @param xPath 
     * @throws XPathExpressionException
     */
    public XPathNodeListIterator(Document xmlDocument, String xPath) throws XPathExpressionException {
        this((NodeList) XPathFactory.newInstance().newXPath().evaluate(xPath, xmlDocument, XPathConstants.NODESET));
    }
    
    /**
     * 
     * @param xmlDocument
     * @param xPath
     * @throws XPathExpressionException 
     * @throws java.io.FileNotFoundException 
     */
    public XPathNodeListIterator(File xmlDocument, String xPath) throws XPathExpressionException, FileNotFoundException, IOException {
        try (FileReader reader = new FileReader(xmlDocument)) {
             this.xmlNodeList = (NodeList) XPathFactory.newInstance().newXPath().evaluate(xPath, new InputSource(reader), XPathConstants.NODESET);
        }
    }
    
    /**
     * 
     * @param xmlDocument
     * @param xPath
     * @throws XPathExpressionException 
     */
    public XPathNodeListIterator(String xmlDocument, String xPath) throws XPathExpressionException {
        this((NodeList) XPathFactory.newInstance().newXPath().evaluate(xPath, new InputSource(xmlDocument), XPathConstants.NODESET));
    }
    
    /**
     * 
     * @param node
     * @param xPath
     * @throws XPathExpressionException 
     */
    public XPathNodeListIterator(Node node, String xPath) throws XPathExpressionException {
        this((NodeList) XPathFactory.newInstance().newXPath().evaluate(xPath, node, XPathConstants.NODESET));
    }
    
    /**
     * 
     * @param xmlNodeList 
     */
    public XPathNodeListIterator(NodeList xmlNodeList) {
        this.xmlNodeList = xmlNodeList;
    }
    
    /**
     * 
     * @return 
     */
    @Override
    public Iterator<Node> iterator() {
        return new XmlNodeListIterator(this.xmlNodeList);
    }
    
    /**
     * 
     */
    private final class XmlNodeListIterator implements Iterator<Node> {
        
        private int index;
        private NodeList xmlNodeList;
        
        /**
         * 
         * @param xmlNode 
         */
        public XmlNodeListIterator(NodeList xmlNodeList) {
            this.index = 0;
            this.xmlNodeList = xmlNodeList;
        }
        
        /**
         * 
         * @return 
         */
        @Override
        public boolean hasNext() {
            return this.xmlNodeList.getLength() > this.index;
        }
        
        /**
         * 
         * @return 
         */
        @Override
        public Node next() {
            return this.xmlNodeList.item(this.index++);
        }
        
        /**
         * 
         */
        @Override
        public void remove() {
            // Not needed
        }
        
    }
    
}
